// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package types2

import (
	"cmd/compile/internal/syntax"
	"fmt"
	"regexp"
	"strconv"
	"strings"
)

// langCompat如果数字
// literal的表示形式与当前语言版本不兼容，则会报告错误。
func (check *Checker) langCompat(lit *syntax.BasicLit) {
	s := lit.Value
	if len(s) <= 2 || check.allowVersion(check.pkg, 1, 13) {
		return
	}
	// len（s）>2 
	if strings.Contains(s, "_") {
		check.versionErrorf(lit, "go1.13", "underscores in numeric literals")
		return
	}
	if s[0] != '0' {
		return
	}
	radix := s[1]
	if radix == 'b' || radix == 'B' {
		check.versionErrorf(lit, "go1.13", "binary literals")
		return
	}
	if radix == 'o' || radix == 'O' {
		check.versionErrorf(lit, "go1.13", "0o/0O-style octal literals")
		return
	}
	if lit.Kind != syntax.IntLit && (radix == 'x' || radix == 'X') {
		check.versionErrorf(lit, "go1.13", "hexadecimal floating-point literals")
	}
}

// allowVersion报告给定包
// 是否允许使用主要版本。少数的
func (check *Checker) allowVersion(pkg *Package, major, minor int) bool {
	// 我们假设进口的包裹都已经过检查，
	// 所以我们只需要检查本地包裹。
	if pkg != check.pkg {
		return true
	}
	ma, mi := check.version.major, check.version.minor
	return ma == 0 && mi == 0 || ma > major || ma == major && mi >= minor
}

type version struct {
	major, minor int
}

// parseGoVersion解析Go版本字符串（如“go1.12”）
// 并返回版本或错误。如果s是空的
// 字符串，则版本为0.0。
func parseGoVersion(s string) (v version, err error) {
	if s == "" {
		return
	}
	matches := goVersionRx.FindStringSubmatch(s)
	if matches == nil {
		err = fmt.Errorf(`should be something like "go1.12"`)
		return
	}
	v.major, err = strconv.Atoi(matches[1])
	if err != nil {
		return
	}
	v.minor, err = strconv.Atoi(matches[2])
	return
}

// goVersionRx匹配Go版本字符串，例如“go1.12”。
var goVersionRx = regexp.MustCompile(`^go([1-9][0-9]*)\.(0|[1-9][0-9]*)$`)
